<template>
    <!--ref属性引用,获取dom操作 listenScroll派发滚动事件 -->
    <scroll class="listview" :data = "data" ref="listview" :probe-type="probeType" :listen-scroll="listenScroll" @scroll="scroll">
          <ul>
           <!--第一层循环 -->
           <li v-for="(group,index) in data" :key="index" class="list-group" ref="listgroup">
             <h2 class="list-group-title" >{{group.id}}</h2> 
             <!--第二层循环 -->   
             <ul class="list-group-items">
                <li @click="selectItem(item)" v-for="(item,index) in group.items" :key="index" class="list-group-item border-1px">
                    <!--图片懒加载 -->
                    <img class="avatar" v-lazy="item.avatar" />
                    <span class="name">{{item.name}}</span>
                </li>
             </ul>
           </li> 
          </ul>
          <!--右侧字母列表 -->
          <div class="list-shortcut" v-show="data.length">
            <ul>
              <li v-for="(item,index) in shortcurList" :key="index"  @touchstart.stop.prevent="onShortcutTouchStart($event)" 
                  @touchmove.stop.prevent="onShortcutTouchMove($event)" @touchend.stop 
                  :class="{'current' : currentIndex === index}" :data-index = "index" class="item" >
                  {{item}}
              </li>
            </ul>
          </div>
          <!--固定title  ref="fixed"/ 修改dom操作 -->
          <div class="list-fixed" v-show="fixedTitle" ref="fixed">
            <div class="fixed-title">{{fixedTitle}}</div>
          </div>
          <!--loading加载页面 -->
          <div class="loading-container" v-show="!data.length">
            <loading></loading>
          </div>
    </scroll>
</template>
<script>
import scroll from '@/components/base/scroll/scroll.vue';
import {getData} from '@/util/dom.js';
import loading from '@/components/base/loading/loading.vue';

const ANCHOR_HEIGHT = 18;
const TITLE_HEIGHT = 25;

export default {
    props: {
      data: {
        type: Array, //接受singer.vue传递map数组
        default: []
      }
    },
    data() {
      return {
        scrollY: -1,
        listenScroll: true,
        listHeight: [],// 也可以存放到data()方法中
        probeType: 3, // 设定BS 实时监测滚动位置
        //currentIndex: 0,// 第一种方法: 高亮的索引值  计算属性会依赖于他使用的data中的属性，只要是依赖的属性值有改变，则自动重新调用一下计算属性
        diff:-1 // 举个栗子:热门的上限与scrollY的差fiff，判断diff差值与高度(样式的固定高度height:25px)之前的高度大小
      };
    },
    computed: {
        // 通过计算属性获取右侧字母列表
        shortcurList() {
            // 闭包的写法
            return this.data.map((group) => {
                return group.id.substr(0, 1);
            });
        },
      
        //固定title
        fixedTitle() {
          console.log('初始化this.scrollY 的第一次值 ',this.scrollY);
          if(this.scrollY > 0){ // 向上滚动thi.scrollY为正数,向下滚动this.scrollY为负数，之前将this.scrollY=0,下拉出现热门重叠效果
            return '';
          }
          let fixedTitle = this.data[this.currentIndex] ? this.data[this.currentIndex].id : '';
          console.log('第一次初始化fixedTitle的值  ',fixedTitle);
          return fixedTitle;
        },

        //第二种方法：高亮的索引值currentIndex
        currentIndex() {
            let listHeight = this.listHeight;
            //console.log('计算属性computed中的listHeight ',listHeight);
            let scrollY =  Math.abs(Math.round(this.scrollY)); // 改变scrollY的数据值
            console.log('-this.scrollY ',scrollY);
            for( let i = 0;i < listHeight.length; i++) {
              let height1 = listHeight[i]; // 上限高度
              let height2 = listHeight[i+1]; // 下限高度
              if(!height2 || (scrollY >= height1 && scrollY < height2 )){  //若height2为下限，则height2不存在,即添加!height2判断
                this.diff = height2 - scrollY; // newY为负值
                console.log('检索右侧字母列表滚动的索引位置',i);
                return i;
              }
            }
            return 0;
        }
    },
    components: {
        scroll,
        loading
    },
    created() {
      // data,props相应的数据会被替换 
      this.touch = {}; // 计算delta的值
    },
    methods: {
        // 第一种方法: 根据字母跳到相应的位置  
        onShortcutTouchStart(event) {
          console.log('触发当前事件 ',event.target);
          let index = getData(event.target,'index');
         
          let firstTouch = event.touches[0];
          console.log('firstTouch触发点的位置 ',firstTouch);
          this.touch.index = index; //记录index,方便touchmove()中获取 技巧在create()方法中设置this.touch = {}
          this.touch.y1 = firstTouch.pageY;// 触发点的位置

          console.log('获取点击当前字母的索引值 ',index);
          this.scrollY = -this.listHeight[index]
          this.$refs.listview.scrollToElement(this.$refs.listgroup[index],0);
        },
        //第二种方法 调用方法 @click="onShortCurTouch2(index,$event)"
        onShortcutTouchStart2(index,event) {
          console.log('事件event的值 ' + event.target);
          console.log('触发index区域  ' + index ); // 触发index区域
          if(!event._constructed){
            return;
          }
          
          //对应的节点scrollToElement()事件
          this.$refs.listview.scrollToElement(this.$refs.listgroup[index],0); // //BS接口，滚动至当前对应的索引区域
        },

        onShortcutTouchMove(event) {
          let firstTouch = event.touches[0];
          console.log('触发点的位置',firstTouch);
          this.touch.y2 = firstTouch.pageY;
          let delta = (this.touch.y2 - this.touch.y1) / ANCHOR_HEIGHT | 0 ; //两点之间的位置差 (| 0 相当于math.floor())
          let moveIndex = parseInt(this.touch.index) + delta;
          console.log('touchmove移动的位置索引index值', moveIndex);

          //对应的节点scrollToElement()事件
          this.scrollY = -this.listHeight[moveIndex]
          this.$refs.listview.scrollToElement(this.$refs.listgroup[moveIndex],0); // //BS接口，滚动至当前对应的索引区域
        },

        //来自@scroll=“scroll”派发监听scroll事件
        scroll(pos) {
          this.scrollY = pos.y; //获取的结果是负值
          //this.scrollY = Math.abs(Math.round(pos.y)) // Math.abs()绝对值
          console.log('监听事件scroll滚动的position.y的高度',this.scrollY);
        },

        /**
         * 1.获取li对应的class样式的区间高度，且存放到listHeight中(即递增的区间数组,标识每个区间对应的高度)
         * 2.定义scrollY，跟踪右侧scrolly的值
         *   使用监听事件scroll，获取position.y的高度
         * 3.scrollY的值与listHeight的索引值进行映射
         *   通过计算属性computed设置 currentIndex()方法，scrollY在listHeight[i] 与 listHeight[i+1]区间中，返回当前索引i
         * 4.通过currentIndex的索引设置对应的样式
         *   :class="{'current' : currentIndex === index}"
         */
        _calculateHeight() { 
          let list = this.$refs.listgroup;// 每个字母下面的姓名集合高度就是每个区块的高度
          let height = 0;
          this.listHeight.push(height);
          for(let i=0; i < list.length; i++){
            let item = list[i];
            height += item.clientHeight; // clientHeight 每个区块的可视高度
            this.listHeight.push(height);
          }
         // console.log('dom渲染完毕,然后计算总高度',this.listHeight);
        },

        // 基础组件,通过listview组件通过$emit()派发cLick事件到最为层组件singer.vue,不做任何的业务逻辑处理
        selectItem(item) {
          this.$emit('select',item);
        }
         
    },
    watch: {
      //当data发生变化需要watch()进行监听,即数据变化到dom变化有延迟反应
      data(){
        setTimeout(() => {
          this._calculateHeight(); // dom渲染完毕,然后计算高度
        },20);
      },

      //scrollY与listHeight进行比较,判断scrollY落在哪个区间段
      // scrollY(newY) {
      //   console.log('watch监听滚动触发',this.listHeight.length);
      //     let listHeight = this.listHeight;//临时变量
      //     for( let i= 0 ;i < listHeight.length; i++) {
      //       let height1 = listHeight[i];//上限高度
      //       let height2 = listHeight[i + 1];//下限高度
      //       //console.log('height1的高度值  ',height1,'height2的高度值  ',height2);
      //       if(!height2 || (-newY >= height1 && -newY < height2 )){  //若height2为下限，则height2不存在,即添加!height2判断
      //         console.log('检索右侧字母列表滚动的索引位置',i);
      //         this.diff = height2 + newY; // newY为负值
      //         this.currentIndex = i;
      //         return ;
      //       }
      //     }
      //     return 0;
      // },

      //监听属性diff的变化
      diff(newVal) {
        let fixedTop = (newVal >0 && newVal < TITLE_HEIGHT) ? newVal - TITLE_HEIGHT : 0;
        if(this.fixedTop === fixedTop) {
          return;
        } 
        this.fixedTop = fixedTop;

        //修改fixedTop的DOM操作 开启GPU加速
        this.$refs.fixed.style.transform = `translate3d(0,${fixedTop}px,0)`;
      }
    }
}
</script>
<style lang="scss" rel="stylesheet/scss">
  @import "@/assets/style/mixin.scss";
  
 .listview {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  .list-group {
    padding-bottom: 30px;
    .list-group-title {
      height: 25px;
      line-height: 25px;
      padding-left: 20px;
      font-size: 12px;
      color: #fff;
      background:#f01414;
    }
    .list-group-items {
      margin: 0 20px;
      .list-group-item {
        display: flex;
        align-items: center;
        padding: 20px 0 0 30px;
        padding-bottom: 10px;
        @include border-1px(rgba(7, 17, 27, 0.1)); //设置1像素
        &:last-child {
            @include border-none;
            padding-bottom: 0px;
            margin-bottom: -10px;
       }
        .avatar {
            width: 50px;
            height: 50px;
            border-radius: 50%
        }
        .name {
            margin-left: 20px;
            color:rgb(147, 153, 159);
            font-size: 14px;
        }
      }
    }
  }
  .list-shortcut {
    position: absolute;
    top: 50%;
    right: 0;
    z-index: 30;
    width: 20px;
    transform: translateY(-50%);// 定义转换，只是用 Y 轴的值
    border-radius: 8px;
    padding: 20px 0;
    text-align: center;
    background: rgba(0, 0, 0, 0.8);
    font-family: Helvetica;
    .item {
     padding: 3px;
     color: #fff;
     font-size: 12px;
     line-height: 10px;
     &.current {
      color: #f01414;
     }
    }
  }
  .list-fixed {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    .fixed-title {
      height: 25px;
      line-height: 25px;
      padding-left: 20px;
      font-size: 12px;
      color: #fff;
      background:#f01414;
    }
  }
  .loading-container {
    position: absolute;
    width: 100%;
    top:50%;
  }
 }
</style>


